// InterruptManager.java
package org.zjx.core.engine;

import org.zjx.core.DecisionNode;
import org.zjx.core.model.InterruptEvent;
import org.zjx.core.state.StateAccessor;

import java.util.Comparator;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.PriorityBlockingQueue;

/**
 * 中断事件管理器 - 游戏AI决策系统中负责管理和处理各种中断事件的核心组件
 *
 * 功能详细描述：
 * 1. 中断事件队列管理：
 *    - 使用PriorityBlockingQueue作为底层存储结构，这是一个线程安全的优先级队列实现
 *    - 队列容量初始化为11，这是一个经过权衡的选择，既不会占用过多内存，又能满足大多数游戏场景的需求
 *    - 排序规则采用复合比较器：首先按中断优先级排序，优先级相同的再按系统纳秒时间戳排序
 *    - 这种排序方式确保高优先级事件总是优先被处理，同优先级事件则按照FIFO原则处理
 *
 * 2. 中断事件生命周期管理：
 *    - 提供register方法用于向系统中注册新的中断事件
 *    - 提供checkInterrupt方法用于检查是否有中断事件被触发，支持两种检查方式：
 *      * 基于状态快照(StateSnapshot)的检查
 *      * 基于状态访问器(StateAccessor)的检查
 *    - 提供handleProcessed方法用于将已处理的中断事件从队列中移除
 *
 * 3. 线程安全设计：
 *    - PriorityBlockingQueue本身是线程安全的，支持多线程并发访问
 *    - 所有公共方法都不需要额外的同步措施，因为底层队列已经保证了线程安全
 *
 * 4. 性能考虑：
 *    - 使用堆结构实现的优先级队列，插入和删除操作的时间复杂度为O(log n)
 *    - peek操作的时间复杂度为O(1)，非常高效
 *    - 系统纳秒时间戳的使用保证了时间比较的精确性
 *
 * 5. 扩展性：
 *    - 中断事件的优先级比较逻辑封装在InterruptEvent类中，便于扩展新的优先级规则
 *    - 触发条件判断委托给InterruptEvent自身实现，支持各种复杂的触发条件
 *
 * 典型使用场景：
 * - 游戏中的紧急事件处理(如玩家突然死亡、道具过期等)
 * - 系统级中断(如超时中断、强制保存等)
 * - 需要优先处理的特殊事件(如VIP玩家请求等)
 */
public class InterruptManager {
    // 使用优先级阻塞队列存储中断事件
    // 初始容量设置为11，这是一个经验值，平衡了内存使用和性能
    // 比较器采用复合比较策略：
    // 1. 首先比较中断事件的优先级(InterruptEvent.Priority枚举值)
    // 2. 如果优先级相同，则比较系统纳秒时间戳(System.nanoTime())
    // 这种设计确保：
    // - 高优先级事件总是先被处理
    // - 同优先级事件按照FIFO(先进先出)原则处理
    private final PriorityBlockingQueue<InterruptEvent> eventQueue =
            new PriorityBlockingQueue<>(11, Comparator
                    .comparing(InterruptEvent::getPriority)
                    .thenComparingLong(e -> System.nanoTime()));


    // 添加自动清理标记
    private final Map<InterruptEvent, Boolean> processedEvents = new ConcurrentHashMap<>();

    /**
     * 注册新的中断事件到管理器
     *
     * 方法说明：
     * - 将给定的中断事件添加到优先级队列中
     * - 由于PriorityBlockingQueue的线程安全特性，此方法可以在多线程环境下安全调用
     * - 如果队列已满(虽然初始容量11在大多数情况下足够)，put操作会阻塞直到有空间可用
     *
     * 参数说明：
     * @param event 要注册的中断事件对象，不能为null(由调用者保证)
     *
     * 使用示例：
     * InterruptEvent event = new SomeInterruptEvent(...);
     * interruptManager.register(event);
     */
    public void register(InterruptEvent event) {
        eventQueue.put(event);
    }

    /**
     * 检查基于状态访问器是否有中断事件被触发
     *
     * 方法说明：
     * - 类似于checkInterrupt(StateSnapshot)方法
     * - 但使用StateAccessor而不是StateSnapshot来检查中断条件
     * - StateAccessor提供了更灵活的状态访问方式，可能包含缓存或其他优化
     *
     * 参数说明：
     * @param accessor 状态访问器对象，提供高效的状态访问接口
     *
     * 返回值：
     * @return 如果有中断事件被触发则返回Optional包装的中断事件，否则返回空Optional
     */
    public Optional<InterruptEvent> checkInterrupt(StateAccessor accessor) {
        return Optional.ofNullable(eventQueue.peek())
                .filter(event -> {
                    if (processedEvents.getOrDefault(event, false)) {
                        eventQueue.remove(event);
                        processedEvents.remove(event);
                        return false;
                    }
                    return event.isTriggered(accessor);
                });
    }

    /**
     * 处理已完成的中断事件，将其从队列中移除
     *
     * 方法说明：
     * - 从优先级队列中移除指定的中断事件
     * - 此方法应该在确认中断事件已被完全处理后调用
     * - 如果事件不在队列头部，remove操作可能需要O(n)时间复杂度
     *
     * 参数说明：
     * @param event 已处理完成的中断事件对象
     *
     * 使用注意事项：
     * - 通常与checkInterrupt方法配合使用：
     *   1. 先调用checkInterrupt检查是否有中断
     *   2. 如果有，处理中断
     *   3. 最后调用handleProcessed通知管理器该事件已处理
     * - 不正确的使用可能导致事件被重复处理或永远滞留在队列中
     */
    public void markAsProcessed(InterruptEvent event, boolean success) {
        if (event.getPriority() == InterruptEvent.Priority.CRITICAL) {
            // 关键中断立即移除
            eventQueue.remove(event);
        } else {
            // 其他中断标记为已处理，下次检查时移除
            processedEvents.put(event, true);
        }

        // 回调处理结果
        if (event.getHandler().get() instanceof ProcessAwareHandler) {
            ((ProcessAwareHandler) event.getHandler().get()).onProcessed(success);
        }
    }

    // 新增处理感知接口
    public interface ProcessAwareHandler extends DecisionNode {
        void onProcessed(boolean success);
    }
}